import Dep from './dep.js'

export default class Observer {
  constructor (data) {
    this.walk(data)
  }
  walk (data) {
    if (typeof data !== 'object') return
    Object.keys(data).forEach(key => {
      this.defineReactive(data, key, data[key])
    })
  }
  defineReactive (data, key, val) {
    const observer = this
    // data 的每个属性都有对应的 dep 对象实例,
    // 用于收集依赖, 发送通知
    const dep = new Dep()
    Object.defineProperty(data, key, {
      enumerable: true,
      constructor: true,
      get () {
        dep.addSub(Dep.target) // 收集依赖
        return val // data[key] 被代理, 会造成无穷递归, 因此要使用闭包中的 val
      },
      set (newVal) {
        if (newVal !== val) {
          val = newVal // 对闭包中的 val 赋值
          observer.walk(newVal) // 若 newVal 是 object, 则代理它的属性, 使得它仍是响应式的
          dep.notify() // 发送通知
        }
      }
    })
    observer.walk(data[key]) // 递归处理子属性
  }
}
